import os
import struct
import math
import time


def _get_file_size(path: str):
    file_stats = os.stat(path)
    return file_stats.st_size


def _get_date_str(h1: int) -> str:
    # TODO: algorithm needs adjustment
    year = int(math.floor(h1 / 2048) + 2004)  # 解析出年
    month = int(math.floor(h1 % 2048 / 100))  # 月
    day = h1 % 2048 % 100  # 日
    return str(year) + '-' + str(month).zfill(2) + '-' + str(day).zfill(2)


def _get_time_str(h2: int) -> str:
    hour = int(math.floor(h2 / 60))  # 小时
    minute = int(h2 % 60)  # 分钟
    if hour < 10:  # 如果小时小于两位, 补0
        hour = "0" + str(hour)
    if minute < 10:  # 如果分钟小于两位, 补0
        minute = "0" + str(minute)

    return str(hour) + ':' + str(minute)


def lc5_read(path: str) -> list:
    mod = _get_file_size(path) % 32

    if mod != 0:
        print('Tail ' + str(mod) + 'bytes dropped!')

    length = int((_get_file_size(path) - mod) / 32)

    ans = []
    f = open(path, "rb")
    for i in range(length):
        temp_bytes = f.read(32)  # 读取一个5分钟数据
        if not temp_bytes:  # 如果没有数据了，就退出
            break
        unpacked = struct.unpack('HHfffffii', temp_bytes)  # 解析数据
        # 00 ~ 01 字节：日期，整型，设其值为num，则日期计算方法为：
        #               year=floor(num/2048)+2004;
        #               month=floor(mod(num,2048)/100);
        #               day=mod(mod(num,2048),100);
        # 02 ~ 03 字节： 从0点开始至目前的分钟数，整型

        date_str = _get_date_str(unpacked[0])  # 解析日期
        time_str = _get_time_str(unpacked[1])  # 解析分时
        unpacked_list = list(unpacked)

        # 04 ~ 07 字节：开盘价，float型
        # 08 ~ 11 字节：最高价，float型
        # 12 ~ 15 字节：最低价，float型
        # 16 ~ 19 字节：收盘价，float型
        # 20 ~ 23 字节：成交额，float型
        # 20 ~ 23 字节：成交量，int型

        unpacked_list[0] = date_str
        unpacked_list[1] = time_str
        ans.append(unpacked_list)

    f.close()

    return ans


def _get_date_time(year_month_day: str, hour_minute: str):
    x = year_month_day
    y = hour_minute
    dt = x + y
    ymr = round(int(x) / 10000 - 2016) * 1300 + int(x) % 10000
    t = int(dt) % 10000
    tt = t // 100 * 60 + t % 100
    return int(ymr), tt


def lc5_write(folder: str, code: str, extend: str, lc5rows: list[list], file_path: str = None):
    if file_path is None:
        file_path = '{}/{}.{}'.format(folder, code, extend)

    succeed = False
    retry_count = 0
    RETRY_MAX = 10
    while not succeed and retry_count < RETRY_MAX:
        try:
            with open(file_path, 'ab+') as f:
                for lc5row in lc5rows:
                    # v1
                    # lc5row[0] = int(get_date_byte(lc5row[0]))
                    # lc5row[1] = int(get_time_byte(lc5row[1]))
                    # bytes = struct.pack('HHfffffii', *lc5row)

                    # v2
                    row0, row1 = _get_date_time(lc5row[0], lc5row[1])
                    lc5row[0] = row0
                    lc5row[1] = row1
                    temp_bytes = struct.pack('hhfffffii', *lc5row)

                    f.write(temp_bytes)
            succeed = True
        except Exception as e:
            print(f'Retry count {retry_count}: ', e)
            retry_count += 1
            time.sleep(0.1)

    if retry_count == RETRY_MAX:
        print('Failed to write: ' + str(file_path))


def test_writer():
    print('测试写入arr')
    test_klines = [
        [
            '20220903',
            '1305',
            float(1503),
            float(1504),
            float(1501),
            float(1502),
            float(352000000.0 / 1000),
            int(3520000 / 100),
            65536,
        ],
        [
            '20220903',
            '1310',
            float(1503),
            float(1504),
            float(1501),
            float(1502),
            float(352000000.0 / 1000),
            int(3520000 / 100),
            65536,
        ],
    ]
    print(test_klines)
    lc5_write('./_cache', 'sz999999', 'lc5', test_klines)


def test_reader():
    print('测试读取lc5')
    #     test_path = './_cache/sh600007.lc5'
    test_path = './tdx/_lc5/sh/sh603050.lc5'
    lc5_rows = lc5_read(test_path)
    for lc5_row in lc5_rows:
        print(lc5_row)
        # ['2025-08-06', '15:00', 16.86, 16.87, 16.85, 16.85, 1546845.0, 91800, 0]
        # date time open high low close amount（元） volume（股）

if __name__ == '__main__':
    from warnings import simplefilter
    simplefilter(action='ignore', category=FutureWarning)

    # test_writer()
    test_reader()
